Skip to content

chore(runway): cherry-pick fix(perps): fix HIP-3 asset ID lookup failure from dual-cache desync cp-7.70.1#27860

Merged
chloeYue merged 1 commit into
release/7.70.1from
runway-cherry-pick-7.70.1-1774354350
Mar 24, 2026
Merged

chore(runway): cherry-pick fix(perps): fix HIP-3 asset ID lookup failure from dual-cache desync cp-7.70.1#27860
chloeYue merged 1 commit into
release/7.70.1from
runway-cherry-pick-7.70.1-1774354350

Conversation

@runway-github
Copy link
Copy Markdown
Contributor

@runway-github runway-github Bot commented Mar 24, 2026

Description

Fix HIP-3 asset ID lookup failure ("Asset ID not found for xyz:BRENTOIL") that blocked trading on HIP-3 markets when navigating
via the old Perps tab layout.

Root cause: Dual-cache desync between #cachedValidatedDexs (string
DEX names) and #cachedAllPerpDexs (raw API objects for perpDexIndex
computation). The standalone preload path
(#getStandaloneValidatedDexs) populated one cache but not the other.
When #buildAssetMapping later ran, it found "xyz" in dexsToMap but
couldn't compute its perpDexIndex because #cachedAllPerpDexs was
null.

Why old Perps tab vs new Homepage Sections: Both layouts sit inside
Wallet/index.tsx, which calls startMarketDataPreload() on mount.
This fires standalone HTTP calls that populate #cachedValidatedDexs
but not #cachedAllPerpDexs.

  • New homepage sections: PerpsSectionWithProvider mounts
    immediately. Stream hooks fire ensureReady() before or concurrently
    with the standalone preload. Since #cachedValidatedDexs is often still
    null, fetchValidatedDexsInternal runs fresh and sets both caches
    correctly.
  • Old tab layout: The Perps tab doesn't mount until the user taps
    it. By that time, startMarketDataPreload() has already completed →
    #cachedValidatedDexs is populated by standalone. When the tab mounts →
    getValidatedDexs()cache hitfetchValidatedDexsInternal is
    never called → #cachedAllPerpDexs stays null → buildAssetMapping
    can't find "xyz".

Changes (1 file, 3 sites):

  1. Root cause fix: #getStandaloneValidatedDexs now sets
    this.#cachedAllPerpDexs = allDexs after a successful perpDexs()
    call, keeping both caches in sync.
  2. Cache poisoning fix: Removed this.#cachedAllPerpDexs = this.#cachedAllPerpDexs ?? [null] from the catch block in
    #buildAssetMapping.
  3. Cache poisoning fix: Replaced persistent if (!cache) { cache = [null] } with local const allPerpDexs = cache ?? [null] — consumers
    read the cache, only the owner writes it.

Changelog

CHANGELOG entry: Fixed a bug where closing positions on HIP-3 markets
(e.g., xyz:BRENTOIL) failed with "Asset ID not found" when navigating
via the Perps tab

Related issues

Fixes: HIP-3 asset ID lookup failure on old Perps tab layout

Manual testing steps

Feature: HIP-3 position management via Perps tab

  Scenario: user closes a HIP-3 position from the old Perps tab
    Given user has an open position on a HIP-3 market (e.g., xyz:BRENTOIL)
    And user is using the old tab layout (homepage redesign v1 disabled)

    When user navigates to the Perps tab
    And user taps close on the xyz:BRENTOIL position
    Then the position closes successfully without "Asset ID not found" error

  Scenario: user opens a HIP-3 position from the old Perps tab
    Given user is on the Perps tab (old layout)

    When user navigates to xyz:BRENTOIL market and places a market order
    Then the order executes successfully with correct asset ID routing

Screenshots/Recordings

Before

Metro logs show the desync:

getValidatedDexs CACHE HIT {"cachedAllNull": true, "dexs": [null, "xyz"]}
buildAssetMapping state  {"allPerpDexsLen": 1, "cachedAllNull": true}
Could not find perpDexIndex for DEX xyz
Asset ID not found for xyz:BRENTOIL

After

Metro logs show both caches in sync:

buildAssetMapping state {"allPerpDexsLen": 8, "cachedAllNull": false, "dexsToMap": [null, "xyz"]}
Asset map state at order time {"assetExistsInMap": true, "hip3AssetsCount": 54, "totalAssetsInMap": 283}
Resolved DEX-specific asset ID {"assetId": 110049, "coin": "xyz:BRENTOIL"}
usePerpsClosePosition: Close result {"success": true, "orderId": "359617825254"}

Pre-merge author checklist

Pre-merge reviewer checklist

  • I've manually tested the PR (e.g. pull and build branch, run the
    app, test code being changed).
  • I confirm that this PR addresses all acceptance criteria described
    in the ticket it closes and includes the necessary testing evidence such
    as recordings and or screenshots.

Note

Medium Risk
Touches HIP-3 market routing/asset-ID mapping in
HyperLiquidProvider, so a mistake could break trading on some perps
markets; scope is small and localized to cache population/fallback
behavior.

Overview
Fixes a HIP-3 asset mapping failure where #cachedValidatedDexs could
be populated via the standalone preload path while #cachedAllPerpDexs
stayed null, leading to missing perpDexIndex during
#buildAssetMapping.

#getStandaloneValidatedDexs() now also populates
#cachedAllPerpDexs after a successful perpDexs() call, and
#buildAssetMapping() no longer “poisons” the shared cache with a
persistent [null] fallback (it uses a local fallback instead).

Written by Cursor
Bugbot
for commit
c925609. This will update automatically
on new commits. Configure
here.

[2898ec8](https://github.com/MetaMask/metamask-mobile/commit/2898ec839aa04320d74dc6bc4ea9b7ec24668d17)

…ure from dual-cache desync cp-7.70.1 (#27854)

## **Description**

Fix HIP-3 asset ID lookup failure (`"Asset ID not found for
xyz:BRENTOIL"`) that blocked trading on HIP-3 markets when navigating
via the old Perps tab layout.

**Root cause**: Dual-cache desync between `#cachedValidatedDexs` (string
DEX names) and `#cachedAllPerpDexs` (raw API objects for `perpDexIndex`
computation). The standalone preload path
(`#getStandaloneValidatedDexs`) populated one cache but not the other.
When `#buildAssetMapping` later ran, it found "xyz" in `dexsToMap` but
couldn't compute its `perpDexIndex` because `#cachedAllPerpDexs` was
null.

**Why old Perps tab vs new Homepage Sections**: Both layouts sit inside
`Wallet/index.tsx`, which calls `startMarketDataPreload()` on mount.
This fires standalone HTTP calls that populate `#cachedValidatedDexs`
but not `#cachedAllPerpDexs`.

- **New homepage sections**: `PerpsSectionWithProvider` mounts
immediately. Stream hooks fire `ensureReady()` before or concurrently
with the standalone preload. Since `#cachedValidatedDexs` is often still
null, `fetchValidatedDexsInternal` runs fresh and sets **both** caches
correctly.
- **Old tab layout**: The Perps tab doesn't mount until the user taps
it. By that time, `startMarketDataPreload()` has already completed →
`#cachedValidatedDexs` is populated by standalone. When the tab mounts →
`getValidatedDexs()` → **cache hit** → `fetchValidatedDexsInternal` is
never called → `#cachedAllPerpDexs` stays null → `buildAssetMapping`
can't find "xyz".

**Changes (1 file, 3 sites)**:

1. **Root cause fix**: `#getStandaloneValidatedDexs` now sets
`this.#cachedAllPerpDexs = allDexs` after a successful `perpDexs()`
call, keeping both caches in sync.
2. **Cache poisoning fix**: Removed `this.#cachedAllPerpDexs =
this.#cachedAllPerpDexs ?? [null]` from the catch block in
`#buildAssetMapping`.
3. **Cache poisoning fix**: Replaced persistent `if (!cache) { cache =
[null] }` with local `const allPerpDexs = cache ?? [null]` — consumers
read the cache, only the owner writes it.

## **Changelog**

CHANGELOG entry: Fixed a bug where closing positions on HIP-3 markets
(e.g., xyz:BRENTOIL) failed with "Asset ID not found" when navigating
via the Perps tab

## **Related issues**

Fixes: HIP-3 asset ID lookup failure on old Perps tab layout

## **Manual testing steps**

```gherkin
Feature: HIP-3 position management via Perps tab

  Scenario: user closes a HIP-3 position from the old Perps tab
    Given user has an open position on a HIP-3 market (e.g., xyz:BRENTOIL)
    And user is using the old tab layout (homepage redesign v1 disabled)

    When user navigates to the Perps tab
    And user taps close on the xyz:BRENTOIL position
    Then the position closes successfully without "Asset ID not found" error

  Scenario: user opens a HIP-3 position from the old Perps tab
    Given user is on the Perps tab (old layout)

    When user navigates to xyz:BRENTOIL market and places a market order
    Then the order executes successfully with correct asset ID routing
```

## **Screenshots/Recordings**

### **Before**

Metro logs show the desync:
```
getValidatedDexs CACHE HIT {"cachedAllNull": true, "dexs": [null, "xyz"]}
buildAssetMapping state  {"allPerpDexsLen": 1, "cachedAllNull": true}
Could not find perpDexIndex for DEX xyz
Asset ID not found for xyz:BRENTOIL
```

### **After**

Metro logs show both caches in sync:
```
buildAssetMapping state {"allPerpDexsLen": 8, "cachedAllNull": false, "dexsToMap": [null, "xyz"]}
Asset map state at order time {"assetExistsInMap": true, "hip3AssetsCount": 54, "totalAssetsInMap": 283}
Resolved DEX-specific asset ID {"assetId": 110049, "coin": "xyz:BRENTOIL"}
usePerpsClosePosition: Close result {"success": true, "orderId": "359617825254"}
```

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile
Coding
Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I've included tests if applicable
- [x] I've documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I've applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches HIP-3 market routing/asset-ID mapping in
`HyperLiquidProvider`, so a mistake could break trading on some perps
markets; scope is small and localized to cache population/fallback
behavior.
> 
> **Overview**
> Fixes a HIP-3 asset mapping failure where `#cachedValidatedDexs` could
be populated via the standalone preload path while `#cachedAllPerpDexs`
stayed `null`, leading to missing `perpDexIndex` during
`#buildAssetMapping`.
> 
> `#getStandaloneValidatedDexs()` now also populates
`#cachedAllPerpDexs` after a successful `perpDexs()` call, and
`#buildAssetMapping()` no longer “poisons” the shared cache with a
persistent `[null]` fallback (it uses a local fallback instead).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
c925609. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
@runway-github runway-github Bot requested a review from a team as a code owner March 24, 2026 12:12
@github-actions
Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@metamaskbot metamaskbot added the team-bots Bot team (for MetaMask Bot, Runway Bot, etc.) label Mar 24, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Smart E2E Test Selection

⏭️ Smart E2E selection skipped - base branch is not main (base: release/7.70.1)

All E2E tests pre-selected.

View GitHub Actions results

Copy link
Copy Markdown
Contributor

@chloeYue chloeYue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@chloeYue chloeYue enabled auto-merge (squash) March 24, 2026 12:16
@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

E2E Fixture Validation — Schema is up to date
16 value mismatches detected (expected — fixture represents an existing user).
View details

@chloeYue chloeYue merged commit 0e0cb25 into release/7.70.1 Mar 24, 2026
194 of 196 checks passed
@chloeYue chloeYue deleted the runway-cherry-pick-7.70.1-1774354350 branch March 24, 2026 13:15
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

size-S team-bots Bot team (for MetaMask Bot, Runway Bot, etc.)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants